home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1993 / Internet Info CD-ROM (Walnut Creek) (1993).iso / networking / ip / ka9q / MacBMsrc.hqx / Mac bm Project / mac_misc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-07  |  16.5 KB  |  714 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include "global.h"
  4.  
  5. #include "HFS.h"
  6. #include <time.h>
  7. #include <types.h>
  8. #include "mac_stat.h"
  9. #include "mac_files.h"
  10.  
  11. extern errno;
  12. struct RemoveIt Head;
  13.  
  14. char *CtoPstr(),*PtoCstr();
  15.  
  16. /*
  17.  * dir: Create a directory listing in a temp file and return the resulting file
  18.  * descriptor. If full == 1, give a full listing in the temp file; if full
  19.  * == 2, give just a list of names in the temp file; if full ==3, output to
  20.  * console with the full listing. full == 0 is same as full == 2.
  21.  */
  22. FILE *
  23. dir(path,full)
  24. char *path;
  25. int full;
  26. {
  27.     WDPBRec MyDisk;
  28.     CInfoPBRec Everything;
  29.     FILE *fp, *fp1;
  30.     OSErr e;
  31.     char *GetPathname();
  32.  
  33.     char *ptr;
  34.     char buff[256];
  35.     char holding_file[256];
  36.     char working_volume[256];
  37.     char dirname[256];
  38.  
  39.     errno = 0;
  40.  
  41. /* open up DIR.TEMP file for the cases we need it, otherwise direct to stdout */
  42.  
  43.     if ( full < 3) {
  44.         if ( ( fp = fopen(dirbm, "w")) == NULL) {
  45.             printf("Open failed, errno = %d\n",errno);
  46.             return((FILE *)NULL);
  47.         }
  48.     }
  49.     else
  50.         fp = stdout;
  51.  
  52. /* start process of getting directory */
  53.     
  54.     MyDisk.ioWDProcID = 0L;
  55.     MyDisk.ioWDDirID = 0L;
  56.     MyDisk.ioVRefNum = 0;
  57.     MyDisk.ioWDVRefNum = 0;
  58.     MyDisk.ioNamePtr = (StringPtr)working_volume;
  59.     if (path[0] == NULL)
  60.         path = ":";
  61.     MoveIt(MyDisk.ioNamePtr, path);
  62.  
  63.     if ( (e = PBOpenWD( &MyDisk, FALSE)) != noErr ) {
  64.  
  65. /*
  66.  * got an error on initial PBOpenWD
  67.  * see if we were passed a file name instead of directory by trying to
  68.  * open it through the library fopen call
  69.  */
  70.         if ( ( fp1 = fopen(path, "r")) == NULL) {
  71.             if (full < 3) {
  72.                 fclose(fp);
  73.                 unlink(dirbm);
  74.             }
  75.             else
  76.                 printf("Can't get directory of '%s'.\n",path);
  77.             return(NULL);
  78.         }
  79.         else {
  80.             fclose(fp1);        /* close the fopen file */
  81.  
  82. /* we were able to open the path as a file.
  83.  * For just the list of file names, strip the latter part
  84.  * of the path and place that in the file. */
  85.  
  86.             if ( (full == 0) || (full == 2) ) {
  87.                 ptr  = rindex(path, ':');
  88.                 if (ptr != NULL)    /* found a :, return stuff to right */
  89.                     ptr++;
  90.                 else
  91.                     ptr = path;        /* no :, return entire path */
  92.                 fprintf(fp,"%s\n", ptr);
  93.                 fclose(fp);            /* close file, reopen as read only */
  94.                 fp = fopen("dir.temp", "r");
  95.                 return(fp);
  96.             }
  97.             else {
  98.     /* we have a single file, and we must return full info. Get it. */
  99.                 sprintf(holding_file, "%s", path);
  100.                 CtoPstr(holding_file);
  101.                 Everything.hFileInfo.ioNamePtr = (StringPtr)holding_file;
  102.                 Everything.hFileInfo.ioVRefNum = MyDisk.ioVRefNum;
  103.                 Everything.hFileInfo.ioFDirIndex = 0;
  104.                 Everything.hFileInfo.ioDirID = 0L;
  105.                 Everything.hFileInfo.ioCompletion = 0;
  106.                                 
  107.                 if ( (e = PBGetCatInfo( &Everything, FALSE)) != fnfErr) {
  108.                     ptr = ctime((long *)&Everything.hFileInfo.ioFlCrDat);
  109.                     ptr +=3;
  110.                     ptr[strlen(ptr)-1] = '\0';
  111.                     ptr[strlen(ptr)-8] = '\0';
  112.                     fprintf(fp,"%c %8ld %8ld-rf %s %s  %s\n",
  113.                         (Everything.hFileInfo.ioFlAttrib & (1<<4))?'d':'-',
  114.                         (Everything.hFileInfo.ioFlAttrib & (1<<4))?
  115.                             0:Everything.hFileInfo.ioFlLgLen,
  116.                         (Everything.hFileInfo.ioFlAttrib & (1<<4))?
  117.                             0:Everything.hFileInfo.ioFlRLgLen, ptr, ptr+19,
  118.                         PtoCstr((char *) Everything.hFileInfo.ioNamePtr));
  119.                 }
  120.                 else
  121.                     printf("Error getting directory: %d\n", e);
  122.             }
  123.             if ( full < 3 ) {
  124.                 fclose(fp);
  125.                 fp = fopen(dirbm, "r");
  126.             }
  127.             return(fp);
  128.         }
  129.     }
  130.  
  131. /* original PBOpenWD worked */
  132.  
  133.     if (full == 3)
  134.         fprintf(fp,"Directory of %s\n",GetPathname(dirname,MyDisk.ioVRefNum));
  135.     
  136.     Everything.hFileInfo.ioNamePtr = (StringPtr)holding_file;
  137.     Everything.hFileInfo.ioVRefNum = MyDisk.ioVRefNum;
  138.     sprintf(Everything.hFileInfo.ioNamePtr, "\p");
  139.     Everything.hFileInfo.ioFDirIndex = 1;
  140.     Everything.hFileInfo.ioDirID = MyDisk.ioWDDirID;
  141.     Everything.hFileInfo.ioCompletion = 0;
  142.  
  143.     while( (e = PBGetCatInfo( &Everything, FALSE)) != fnfErr) {
  144.         if ( e == noErr ) {
  145.             if( full == 0) {
  146.                 fprintf(fp, "%s\n",
  147.                      PtoCstr((char *) Everything.hFileInfo.ioNamePtr));
  148.             }
  149.             else {    
  150.                 ptr = ctime((long *)&Everything.hFileInfo.ioFlCrDat);
  151.                 ptr +=3;
  152.                 ptr[strlen(ptr)-1] = '\0';
  153.                 ptr[strlen(ptr)-8] = '\0';
  154.                 fprintf(fp,"%c %8ld %8ld-rf %s %s  %s\n",
  155.                     (Everything.hFileInfo.ioFlAttrib & (1<<4))?'d':'-',
  156.                     (Everything.hFileInfo.ioFlAttrib & (1<<4))?
  157.                         0:Everything.hFileInfo.ioFlLgLen,
  158.                     (Everything.hFileInfo.ioFlAttrib & (1<<4))?
  159.                         0:Everything.hFileInfo.ioFlRLgLen, ptr, ptr+19,
  160.                     PtoCstr((char *) Everything.hFileInfo.ioNamePtr));
  161.             }
  162.             
  163.             Everything.hFileInfo.ioFlLgLen = 0;
  164.             Everything.hFileInfo.ioFDirIndex++;
  165.  
  166.         }
  167.         else
  168.             break;        /* go an error other than fnfErr: break */
  169.  
  170.         Everything.hFileInfo.ioDirID = MyDisk.ioWDDirID;
  171.     }
  172.  
  173. /*
  174.  * either the PBGetCatInfo finally encountered a fnfErr, or some other error
  175.  * occurred. If we were writing a file, close it then reopen it before returning
  176.  * the file pointer to our caller.
  177.  */
  178.     PBCloseWD(&MyDisk, FALSE);
  179.     if ( full < 3) {
  180.         fclose(fp);
  181.         fp = fopen(dirbm, "r");
  182.     }
  183.     return(fp);
  184. }
  185.  
  186. /*
  187.  * MoveIt: this is like a bcopy, but uses pascal string type
  188.  * of data.
  189.  */
  190.  
  191. MoveIt(to,from)
  192. char *to, *from;
  193. {
  194.     int size;
  195.  
  196.     memset(to, 0, 3);
  197.     to[0] = size = strlen(from);
  198.     if ( size <= 0)
  199.     {
  200.         printf("MoveIt: size <= 0 (%d\n", size);
  201.         return;
  202.     }
  203.     to++;
  204.     while( size-- )
  205.         *to++ = *from++;    
  206. }
  207.  
  208. /*
  209.  * tmpfile: create a temporary file.  Remember it so we can delete it later because
  210.  * the mac does not allow the file to be deleted when it is open.
  211.  */
  212.  
  213. FILE *
  214. tmpfile()
  215. {
  216.     FILE *tmp;
  217.     char *mktemp();
  218.     char *ptr;
  219.     char tmpname[16]; 
  220.     
  221.     strcpy(tmpname,"MLMxxxxxxxx");
  222.     if ( ( ptr = malloc(strlen(temppath)+strlen(tmpname)+1)) == NULLCHAR) {
  223.         printf("tmpfile: can't allocate memory.\n");
  224.         return(NULL);
  225.     }
  226.     (void) mktemp(tmpname);            /* replace the xxxxxxxx with something else */
  227.     sprintf(ptr,"%s%s",temppath,tmpname);
  228.     if ( ( tmp = fopen(ptr, "w+") ) == NULL) {
  229.         printf("tmpfile: could not create temp file (%s)\n", ptr);
  230.         (void)free(ptr);    /* free up our original name storage */
  231.         return(NULL);
  232.     }
  233.  
  234. /* save away the name of the file so we can delete it when exiting (ignore
  235.  * errors, if we can't delete at exit it won't harm anything). */
  236.  
  237.     NLadd_name(ptr,&Head);
  238.     (void)free(ptr);    /* free up our original name storage */
  239.     return (tmp);        /* return file pointer to the file we opened */
  240. }
  241.  
  242. /*
  243.  * mktemp: make temporary filename and return a pointer to it.
  244.  *
  245.  * method: if the string passed has an X in it, insert an 8-digit hexadecimal
  246.  * number based on the current tick count starting at the first X position. If the
  247.  * string passed has no X, insert the 8-digit hexadecimal number starting at
  248.  * the beginning of the string. No action is taken if there is insufficient room
  249.  * to insert the number without extending the passed string.
  250.  */
  251.  
  252. char *mktemp(ff)
  253. char *ff;
  254. {
  255.     char *ptr;
  256.     if ( ( ptr = index(ff, 'x') ) == NULL)
  257.         ptr = ff;
  258.     if (strlen(ptr) >= 8)
  259.         sprintf(ptr, "%lx", (long)TickCount());
  260.     return(ff);
  261. }
  262.  
  263. static WDPBRec Mydisk;
  264. static CInfoPBRec Everything;
  265. static IsOpen = 0;    /* tells me that the file is open */
  266. static char *name_ptr;
  267. static char working_dir[255];
  268. static char holding_file[255];
  269. static     char working_vol[255];
  270.  
  271. static struct RemoveIt search_result;
  272.  
  273. /*
  274.  * filedir: search for a file.
  275.  *
  276.  * NOTE: this is not a general file search routine.
  277.  * The search path must have the filename in the form xxxxx.yyyyy. This search
  278.  * code will look for files that match the .yyyyy.
  279.  *
  280.  * filedir(path,value,dest)
  281.  * The name of the matched file (just the filename, no folder/path info) will
  282.  * be returned in dest. An empty dest (first value NULL) indicates no match.
  283.  *
  284.  * value =0: start a new search thread.
  285.  * value =1: use the last search thread, provide the next file match.
  286.  */
  287. int filedir(path,value,dest)
  288. char *path;
  289. int value;
  290. char *dest;
  291. {
  292.     WDPBRec MyDisk;
  293.     CInfoPBRec Everything;
  294.     FILE *fp1;
  295.     OSErr e;
  296.  
  297.     char *GetPathname();
  298.     char *ptr,*name_ptr;
  299.     char keep;
  300.     char holding_file[256];
  301.     char working_volume[256];
  302.     char search_string[256];
  303.     char *NLreturn_first();
  304.  
  305.     dest[0] = NULL;        /* initialize return value */
  306.     
  307. /* first, see if this is a new search thread. If so, we must first clean up any
  308.  * outstanding search_result structure.
  309.  */
  310.     if (value == 0) {
  311.         NLdelete_all(&search_result);
  312.         errno = 0;
  313.  
  314.     /* start process of getting directory */
  315.         MyDisk.ioWDProcID = 0L;
  316.         MyDisk.ioWDDirID = 0L;
  317.         MyDisk.ioVRefNum = 0;
  318.         MyDisk.ioWDVRefNum = 0;
  319.         MyDisk.ioNamePtr = (StringPtr)working_volume;
  320.  
  321.     /* establish our path name */
  322.         if (path[0] == NULL)
  323.             strcpy(search_string,":");
  324.         else
  325.             strcpy(search_string,path);
  326.  
  327.     /* see if we have a path with folder info or just a filename */
  328.         if ( (ptr = rindex(search_string, ':')) != NULL) {
  329.             keep = *ptr;
  330.             *ptr = '\0';
  331.             MoveIt(MyDisk.ioNamePtr, search_string);
  332.             *ptr = keep;
  333.         }
  334.         else
  335.             MoveIt(MyDisk.ioNamePtr, search_string);
  336.  
  337.         if ( ( name_ptr = rindex( search_string, '.')) != NULL)
  338.             name_ptr++;
  339.         else
  340.             name_ptr = "";
  341.  
  342.     /*open the working directory */
  343.         if ( (e = PBOpenWD( &MyDisk, FALSE) != noErr) ) {
  344.  
  345.     /* got an error on initial PBOpenWD - see if we were passed a file name
  346.      * instead of directory by trying to open it through the library fopen call
  347.      */
  348.             if ( ( fp1 = fopen(search_string, "r")) == NULL)
  349.                 return(-1);
  350.             fclose(fp1);        /* close the fopen file */
  351.  
  352.     /* we were able to open the path as a file - return the single file name */
  353.  
  354.             ptr  = rindex(search_string, ':');
  355.             if (ptr != NULL)    /* found a :, return stuff to right */
  356.                 ptr++;
  357.             else
  358.                 ptr = search_string;        /* no :, return entire path */
  359.             strcpy(dest,ptr);    /* copy our single result */
  360.             return(0);
  361.         }
  362.  
  363.     /* original PBOpenWD worked */
  364.     
  365.         Everything.hFileInfo.ioNamePtr = (StringPtr)holding_file;
  366.         Everything.hFileInfo.ioVRefNum = MyDisk.ioVRefNum;
  367.         Everything.hFileInfo.ioFDirIndex = 1;
  368.         Everything.hFileInfo.ioDirID = MyDisk.ioWDDirID;
  369.         Everything.hFileInfo.ioCompletion = 0;
  370.  
  371.         while( (e = PBGetCatInfo( &Everything, FALSE)) != fnfErr) {
  372.             if ( e == noErr ) {
  373.  
  374.                 PtoCstr(holding_file);
  375.                 if ( ( ptr = rindex( holding_file, '.')) != NULL) {
  376.                     ptr++;
  377.                     if ( strncmp(ptr, name_ptr, strlen(name_ptr)) == 0)
  378.                         NLadd_name(holding_file, &search_result);
  379.                 }
  380.                 Everything.hFileInfo.ioFlLgLen = 0;
  381.                 Everything.hFileInfo.ioFDirIndex++;
  382.                 Everything.hFileInfo.ioDirID = MyDisk.ioWDDirID;
  383.             }
  384.             else
  385.                 break;        /* got an error other than fnfErr: break */
  386.         }
  387.  
  388. /* either the PBGetCatInfo finally saw a fnfErr, or some other error occurred. */
  389.  
  390.         PBCloseWD(&MyDisk, FALSE);
  391.     }
  392.  
  393. /* either we are on a search continuation or have finished the data gathering phase */
  394.  
  395.     if ((ptr = NLreturn_first(&search_result)) != NULL) {
  396.         strcpy(dest,ptr);
  397.         NLdelete_first(&search_result);
  398.         return(0);
  399.     }
  400.     return(-1);
  401. }
  402.  
  403. /*
  404.  * Bzero: zero out a buffer
  405.  */
  406.  
  407. bzero(str, cnt)
  408. char *str;
  409. int    cnt;
  410. {
  411.     while(cnt-- != 0)
  412.         *str++ = '\0';
  413. }
  414.  
  415. system(str)
  416. char *str;
  417. {
  418.     printf("The system subroutine call is not implemented on this version.\n");
  419.     return(-1);
  420. }
  421.  
  422. isatty()
  423. {
  424.     return(1);
  425. }
  426.  
  427. /*
  428.  * Access: check the file for access permission.  Some of this has to be faked on
  429.  * a Mac, since it does not have access bits.
  430.  *
  431.  * returned value = 0: OK
  432.  * returned value = 1: reject
  433.  */
  434.  
  435. int
  436. access(str, perm)
  437.  char *str;
  438.  int perm;
  439. {
  440.     FILE *fptr;
  441.     CInfoPBRec    paramBlock;
  442.     OSErr e;
  443.  
  444.     paramBlock.hFileInfo.ioCompletion = 0;
  445.     paramBlock.hFileInfo.ioVRefNum = 0;
  446.     paramBlock.hFileInfo.ioFDirIndex = 0;
  447.     paramBlock.hFileInfo.ioDirID = 0;
  448.     paramBlock.hFileInfo.ioNamePtr = (StringPtr) CtoPstr(str);
  449.  
  450.     /*
  451.      * Get info on file named in ioNamePtr
  452.      */
  453.      
  454.     e = PBGetCatInfo( ¶mBlock, FALSE);
  455.     PtoCstr(str);
  456.     
  457.     /*
  458.      * if there is an error then find out if the file is present.  If so
  459.      * see if user wants to create the file
  460.      */
  461.      
  462.     if ( e != noErr ) {
  463.         if ( ( e == fnfErr) && (perm == 2))
  464.             return(0);
  465.         else
  466.             return(1);
  467.     }
  468.     /*
  469.      * check to see if the file is locked or open.  refuse it if it is.
  470.      */
  471.      
  472.     if ( (BitTst( ¶mBlock.hFileInfo.ioFlAttrib, 0) 
  473.             || BitTst( ¶mBlock.hFileInfo.ioFlAttrib, 7) ) && perm == 4 )
  474.         return(1);
  475.     else
  476.         return(0);
  477. }
  478.  
  479. stat(str, buf)
  480.  char *str;
  481.  struct stat *buf;
  482. {
  483.     FILE *fptr;
  484.     CInfoPBRec    paramBlock;
  485.     OSErr e;
  486.     char *CtoPstr();
  487.  
  488.     paramBlock.hFileInfo.ioCompletion = 0;
  489.     paramBlock.hFileInfo.ioVRefNum = 0;
  490.     paramBlock.hFileInfo.ioFDirIndex = 0;
  491.     paramBlock.hFileInfo.ioDirID = 0;
  492.     paramBlock.hFileInfo.ioNamePtr = (StringPtr) CtoPstr(str);
  493.  
  494.     /*
  495.      * Get info on file named in ioNamePtr
  496.      */
  497.      
  498.     e = PBGetCatInfo( ¶mBlock, FALSE);
  499.     PtoCstr(str);
  500.     
  501.     /*
  502.      * if there is an error then find out if the file is present.  If so
  503.      * see if user wants to create the file
  504.      */
  505.      
  506.     if ( e != noErr )
  507.     {
  508.         if ( e == fnfErr ) 
  509.         {
  510.             return(0);
  511.         }
  512.         else
  513.         {
  514.             return(1);
  515.         }
  516.     }
  517.  
  518.     buf->st_size = paramBlock.hFileInfo.ioFlLgLen + paramBlock.hFileInfo.ioFlRLgLen;
  519.     buf->st_mtime = paramBlock.hFileInfo.ioFlMdDat;
  520.     return(0);
  521. }
  522.  
  523. static char *mptr = "MLMXXXXXX";
  524. char *
  525. tmpnam(str)
  526. char *str;
  527. {
  528.     long tt;
  529.     char *ptr;
  530.     if (str == NULL)
  531.     {
  532.         str = mptr;
  533.     }
  534.     ptr = str;
  535.     ptr += 3;
  536.     tt = TickCount();
  537.     tt &= 0xffffffff;
  538.     sprintf(ptr, "%ld", tt);
  539.     return(str);
  540. }
  541.  
  542. /* get environment: only use within KA9Q is to retrieve the local timezone.
  543.  */
  544.  
  545. char *getenv(str)
  546. char *str;
  547. {
  548.     return(tzname[0]);
  549. }
  550.  
  551. mac_cleanup()
  552. {
  553.     struct RemoveIt *tp,*tp1;
  554.  
  555. /* get our first entry, delete string but leave structure with null pointer */
  556.     tp = &Head;
  557.     if (tp->name_ptr != NULL) {
  558.         (void)unlink(tp->name_ptr);
  559.         (void)free(tp->name_ptr);
  560.     }
  561.     tp1 = tp->next;            /* prepare for loop that follows */
  562.     tp->next = NULL;        /* initialize pointer to next entry */
  563.     tp->name_ptr = NULL;    /* initialize string pointer */
  564.     
  565. /* now traverse list */
  566.     while(tp1 != NULL) {
  567.         tp = tp1;            /* get pointer to current entry */
  568.         tp1 = tp->next;        /* prepare pointer to next entry */
  569.         if (tp->name_ptr != NULL) {
  570.             (void)unlink(tp->name_ptr);
  571.             (void)free(tp->name_ptr);
  572.         }
  573.         (void)free(tp);
  574.     }
  575.     unlink(dirbm);        /* delete the dirbm.temp file */
  576. }
  577. /* ------------------*/
  578. /* name-list manager */
  579. /* ------------------*/
  580.  
  581. /*
  582.  * NLadd_name
  583.  * This routine adds an additional name to a list of structures. A success/failure
  584.  * indication is returned for the caller to examine (0=success, -1=failure).
  585.  */
  586.  
  587. int NLadd_name(name,first)
  588. char *name;
  589. struct RemoveIt *first;
  590. {
  591.     struct RemoveIt *rptr;
  592.  
  593. /* get our first entry, traverse list to reach end */
  594.     rptr = first;
  595.     while(rptr->next != NULL ) {
  596.         rptr = rptr->next;
  597.     }
  598.  
  599. /* allocate space for another list entry */
  600.     
  601.     if ( (rptr->next = (struct RemoveIt *)malloc(sizeof (struct RemoveIt)) ) == NULL) {
  602.         printf("Could not allocate memory for structure RemoveIt\n");
  603.         return(-1);
  604.     }
  605.  
  606. /* allocate space for the name */
  607.  
  608.     if ( (rptr->name_ptr = malloc(strlen(name)+1) ) == NULL) {
  609.         rptr->next = NULL;
  610.         printf("Could not allocate memory for %s\n", name);
  611.         return(-1);
  612.     }
  613.  
  614. /* copy the name to the allocated area */
  615.     strcpy(rptr->name_ptr, name);
  616.     
  617. /* jump to last entry on list and initialize */
  618.     rptr = rptr->next;
  619.     rptr->next = NULL;        /* initialize pointer to next entry */
  620.     rptr->name_ptr = NULL;    /* initialize string pointer */
  621.     
  622.     return (0);        /* return success indication */
  623. }
  624.  
  625. /*
  626.  * NLdelete_all
  627.  * This routine deletes all the storage allocated for the list of structures, and leaves
  628.  * the first entry set with a null pointer.
  629.  */
  630.  
  631. int NLdelete_all(first)
  632. struct RemoveIt *first;
  633. {
  634.     struct RemoveIt *rptr;
  635.     struct RemoveIt *next;
  636.  
  637. /* get our first entry, delete string but leave structure with null pointer */
  638.     rptr = first;
  639.     next = rptr->next;
  640.     if (rptr->name_ptr != NULL)
  641.         (void) free(rptr->name_ptr);
  642.     rptr->next = NULL;        /* initialize pointer to next entry */
  643.     rptr->name_ptr = NULL;    /* initialize string pointer */
  644.     
  645. /* now traverse list */
  646.     while(next != NULL) {
  647.         rptr = next;
  648.         next = rptr->next;
  649.         if (rptr->name_ptr != NULL)
  650.             (void) free(rptr->name_ptr);
  651.         (void) free(rptr);
  652.     }
  653.  
  654.     return (0);        /* return success indication */
  655. }
  656.  
  657. /*
  658.  * NLdelete_first
  659.  * This routine deletes the first entry.
  660.  */
  661.  
  662. int NLdelete_first(first)
  663. struct RemoveIt *first;
  664. {
  665.     struct RemoveIt *rptr;
  666.  
  667. /* get our first entry, delete string if there is one */
  668.  
  669.     rptr = first->next;
  670.     if (first->name_ptr != NULL)
  671.         (void)free(first->name_ptr);    /* delete string */
  672.  
  673. /* if there are more structures, copy the next one into the first, then
  674.  * delete the storage of the next one */
  675.  
  676.      if (rptr != NULL) {
  677.         first->next = rptr->next;    /* copy pointers */
  678.         first->name_ptr = rptr->name_ptr;
  679.         (void)free(rptr);            /* delete structure */
  680.     }
  681.     
  682.     return (0);        /* return success indication */
  683. }
  684.  
  685. /*
  686.  * NLreturn_first
  687.  * This routine returns the string pointer in the first entry.
  688.  */
  689.  
  690. char *NLreturn_first(first)
  691. struct RemoveIt *first;
  692. {
  693.  
  694. /* get our first entry, return string pointer component */
  695.  
  696.     return(first->name_ptr);
  697. }
  698.  
  699. char *strtac(s1,s2)
  700.    register char *s1,*s2;
  701.    {
  702.    register char *result=s1;
  703.    register int n = strlen(s2);
  704.    
  705.    while (*s1++)
  706.       ;
  707.    while(--s1>=result)
  708.       *(s1+n)= *s1;
  709.       s1++;
  710.    while (*s2)
  711.       *s1++=*s2++;
  712.    return result;
  713.    }
  714.